#pragma once
#include <memory>
#include <iostream>
#include "mytcp.hpp"
#include <unistd.h>
#include <sys/select.h>
#include<poll.h>
class PollServer
{
    const static int size = 4096;
public:
    PollServer(int port)
        : _listensockfd(std::make_unique<TcpSocket>()), _isrunning(false)
    {
        _listensockfd->BuildListenMethod(port);
        // 把fds并且将listenfd放在第一个
        for (int i = 0; i < size; i++)
        {
            _fds[i].fd=-1;
            _fds[i].events=0;
            _fds[i].revents=0;
        }
        _fds[0].fd = _listensockfd->Fd();
        _fds[0].events=POLLIN;
        //std::cout<<"_listenfd="<<_listensockfd->Fd()<<std::endl;
    }
    void Accepter()
    {
        Addr client;
        int fd = _listensockfd->Accept(&client);
        if (fd >= 0)
        {
            LOG(LogLevel::DEBUG) << "new link,fd=:" << fd<<",client is"<<client.GetAddr();
        }
        //将收到的fd放到辅助数组中
        int pos=0;
        for(;pos<size;pos++)
        {
            //此时辅助数组还没有满,所以可以直接跳出循环然后加入该fd
            if(_fds[pos].fd==-1)
            {
                break;
            }
        }
        if(pos==size)
        {
            //满了,则将该文件描述符关闭
            close(fd);
        }
        else
        {
            //加入该fd,并且关心他的读事件
            _fds[pos].fd=fd;
            _fds[pos].events=POLLIN;
            _fds[pos].revents=0;
        }
    }
    void Recver(int i)
    {
        char buffer[1024];
        int n=recv(_fds[i].fd,buffer,sizeof(buffer)-1,0);
        if(n>0)
        {
            //正常读
            buffer[n-1]=0;
            LOG(LogLevel::DEBUG)<<"client says@"<<buffer;
        }
        else if(n==0)
        {
            //此时客户端退出
            LOG(LogLevel::DEBUG)<<"client quit...";
            //不关心该fd并且关闭该fd
            _fds[i].fd=-1;
            _fds[i].events=0;
            _fds[i].revents=0;
            close(_fds[i].fd);
        }
        else
        {
            //recv韩束出错
            LOG(LogLevel::FATAL)<<"recv error...";
            //不关心该fd并且关闭该fd
            _fds[i].fd=-1;
            _fds[i].events=0;
            _fds[i].revents=0;
            close(_fds[i].fd);
        }
    }
    void Dispatcher()
    {
        std::cout<<"进入dispatcher逻辑块"<<std::endl;
        for (int i = 0; i < size; i++)
        {
            if (_fds[i].fd == -1)
            {
                continue;
            }
            if (_fds[i].revents&POLLIN)//判断时间是否就绪
            {
                // 该fd存在于数组中
                if (_fds[i].fd == _listensockfd->Fd())
                {
                    //将该fd加入辅助数组中
                    //std::cout<<"找到listenfd,进入accepter逻辑块"<<std::endl;
                    Accepter();
                }
                else
                {
                    // 关心读事件
                    std::cout<<"进入recver逻辑块"<<std::endl;
                    Recver(i);
                }
            }
            // else
            // {
            //     std::cout<<"不存在_fd_array["<<i<<"]"<<std::endl;
            // }
        }
        // 开始accept
        //  int fd=_listensockfd->Accept();
        //  if(fd>=0)
        //  {
        //      LOG(LogLevel::DEBUG)<<"new link,fd=:"<<fd;
        //  }
    }
    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // if(FD_ISSET(_listensockfd->Fd(),&readfd))
            // {
            //     std::cout<<"readfd中存在_listenfd"<<std::endl;
            // }
            // else
            // {
            //     std::cout<<"readfd中不存在_listenfd"<<std::endl;
            // }
            int n=poll(_fds,size,-1);
            // int n=select(_listensockfd->Fd()+1,readfd,nullptr,timeout);
            switch (n)
            {
            case -1:
                LOG(LogLevel::ERROR) << "select error!";
                break;
            case 0:
                LOG(LogLevel::DEBUG) << "wait overtime!";
                break;
            default:
                LOG(LogLevel::DEBUG) << "有事件就绪,n=" << n;
                // 开始处理事件
                Dispatcher();
                break;
            }
        }
        _isrunning=false;
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~PollServer()
    {
    }

private:
    std::unique_ptr<Socket> _listensockfd;
    bool _isrunning;
    // 因为select之后,原来fd_set中的值就会改变,所以需要一个辅助数组记录
    struct pollfd _fds[size];
};